﻿package com.dcliment.jukebox.controllers
{
	import com.dcliment.elements.MetricsElement;
	import com.dcliment.events.MetricsEvent;
	import com.dcliment.jukebox.elements.AbstractContent;
	import com.dcliment.jukebox.elements.IContent;
	import com.dcliment.jukebox.events.JukeBoxEvent;
	import com.dcliment.jukebox.models.ContentControllerModel;
	import com.dcliment.jukebox.models.ContentModel;
	import com.dcliment.jukebox.models.IJukeBoxModel;
	import com.dcliment.utils.GraphicUtil;
	import com.dcliment.utils.XMLUtils;
	import com.greensock.TweenMax;
	import com.greensock.events.LoaderEvent;
	import com.greensock.loading.LoaderMax;
	import com.greensock.loading.SWFLoader;
	import com.greensock.loading.core.LoaderItem;
	import com.greensock.loading.display.ContentDisplay;
	
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.Security;
	import flash.system.SecurityDomain;
	import flash.utils.Dictionary;
	
	/**
	 * 
	 * @author dcliment
	 * version 1.0; 
	 */	
	public class JukeContentController extends EventDispatcher
	{
		
		private var _jukeBoxModel:IJukeBoxModel;
		private var _view:Sprite;
		private var _jukeboxController:IJukeBox;
		private var _ccModel:ContentControllerModel;
		// preloading
		private var _preLoad:LoaderMax;
		// CONTENT 
		private var _contentDic:Dictionary;
		private var _contentMC:ContentDisplay;//SwfLoader DisplayObject
		private var _contentRaw:*; // this is the rawContent from the _contentMC
		private var _contentI:IContent; // interface so i can evoke start stop and other functions
		
		
		private var _pausedByUser:Boolean;
		
		public function JukeContentController($model:IJukeBoxModel, $view:Sprite, $controller:IJukeBox)
		{
			_jukeBoxModel 		= $model;
			_view 				= $view;
			_jukeboxController 	= $controller;
				
			//---------------------------------
			// Dictionary of assets
			_contentDic = new Dictionary(false);
			
			//---------------------------------
			// EVENTS
			_jukeBoxModel.addEventListener(JukeBoxEvent.ID_CHANGE, onIDChange, false, 0, true);
			_jukeBoxModel.addEventListener(JukeBoxEvent.PLAY_STATE_CHANGE, onPlayStateChange, false, 0, true);
		}
		public function setup($model:ContentControllerModel):void
		{
			_ccModel = $model;
			
			_view.x = _ccModel.posX;
			_view.y = _ccModel.posY;
			
			//-------------------------
			// MASK content area
			if(_ccModel.shouldMask)
				GraphicUtil.makeMask(_view, _ccModel.width, _ccModel.hieght, _ccModel.posX, _ccModel.posY);
			
			// --------------------
			// Pre loading of assets
			var list:XMLList = _ccModel.pagesList;
			_preLoad = new LoaderMax({name:"preloadQueue", onProgress:preloadProgressHandler, onComplete:onPreloadComplete, onError:preloadErrorHandler});
			
			for(var i:int = 0; i < list.length(); i++)
			{
				
				var contentModel:ContentModel 		= new ContentModel();
					contentModel.src 	= XMLUtils.getXMLAttribute(list[i], "src", String, null, true);
					contentModel.id 	= XMLUtils.getXMLAttribute(list[i], "id", String, null, true);
					contentModel.time 	= XMLUtils.getXMLAttribute(list[i], "time", Number, null, true);
				
				_contentDic[contentModel.id] = contentModel;
					
				createQueue(contentModel);
			
			}			
			
			_preLoad.load();
			
			_pausedByUser=false;
			
		}
		
		public function reset():void
		{
			
			
			if(_contentMC)
			{
				_view.removeChild(_contentMC);
				
				_contentI.reset();
					
				_contentMC = null;
				_contentI = null;
				
				// Remove Metrics EventListeners
				_contentRaw.removeEventListener(MetricsEvent.TRACK_ELEMENT, contentMetricsTracked);
				_contentRaw.removeEventListener(JukeBoxEvent.PLAY_JUKE,_onPlayPauseJuke);
				_contentRaw.removeEventListener(JukeBoxEvent.PAUSE_JUKE,_onPlayPauseJuke);
				_contentRaw = null;
			}
			
			addNewContent();
		}
		private function addNewContent():void
		{
			_contentMC = LoaderMax.getContent(String(_jukeBoxModel.id));
			_contentRaw = _contentMC.rawContent;
			
			try
			{
				_contentI = IContent(_contentRaw); // key step is the next one that gets the rawContent from the ContentDisplay
			}
			catch(e:Error)
			{
				var l:LoaderItem = _contentMC.loader;
				
				throw new Error("ContentController ERROR :: loaded Swf = " + l.url + " :: Does not implement IContent");
			}
			
			_contentRaw.addEventListener(MetricsEvent.TRACK_ELEMENT, contentMetricsTracked, false, 0, true);
			_contentRaw.addEventListener(JukeBoxEvent.PLAY_JUKE,_onPlayPauseJuke, false, 0, true);
			_contentRaw.addEventListener(JukeBoxEvent.PAUSE_JUKE,_onPlayPauseJuke, false, 0, true);
			
			_view.addChild(_contentMC);
			
			// tween and onComplete start Content
			TweenMax.to(_view, _ccModel.tSpd, {autoAlpha:1, ease:_ccModel.tEasing, onComplete:playContent});
			
			_contentI.reset();
		}
		
		private function _onPlayPauseJuke(e:JukeBoxEvent):void{
			
		
			switch( e.type){
				
				
				case JukeBoxEvent.PAUSE_JUKE:
					_jukeboxController.pauseApp();
				//	_jukeBoxModel.playState = false;	
				break;
				
				case JukeBoxEvent.PLAY_JUKE:
					_jukeboxController.resumeApp();
				//	_jukeBoxModel.playState = true;
				break;
				
			}
		}
		
		
		private function playContent():void
		{
			if(_contentI && _jukeBoxModel.playState)
			{
		
				_contentI.start();
			}
		}
		//--------------------------------------------
		// Event listeners
		private function onIDChange(e:JukeBoxEvent):void
		{
			
			// :: First pause content ::
			if(_contentI)
				_contentI.pause();
				
			
			// Then tween :: on complete reset()
			TweenMax.to(_view, _ccModel.tSpd, {autoAlpha:0, ease:_ccModel.tEasing, onComplete:this.reset});
				
		}
		/**
		 * Listens if AppModel.playState changes. Play or pause content if
		 * @param e 
		 */		
		private function onPlayStateChange(e:JukeBoxEvent):void
		{
			
		
			if(!_contentMC)
				return;
			
			if(_jukeBoxModel.playState){
				
				
				if(_pausedByUser){
					
					_contentI.resume();
					_pausedByUser = false;
				}
				
			}
			else{
				
				_contentI.pause();
				_pausedByUser = true;
			}
		}
		//--------------------------------------------------------
		// metrics tracking
		private function contentMetricsTracked(e:MetricsEvent):void
		{
			var metricsElement:MetricsElement = e.data;
			
			_jukeboxController.track(metricsElement);

			
			e.stopPropagation();
			
		}
		//---------------------------------------------
		// PRELOADERS
		private function createQueue($contentModel:ContentModel):void
		{

			var appDomain:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); // OK.... applicationDomain has to be currDomain for you to cast as IContent
			var cxt:LoaderContext = new LoaderContext(false, appDomain);
			
			if(Security.sandboxType == Security.REMOTE)
			{
				cxt.securityDomain = SecurityDomain.currentDomain; // this is as a failsafe if loaded from server
			}
			
			_preLoad.append(new SWFLoader($contentModel.src, {name:$contentModel.id, context:cxt, onComplete:onSwfLoadComplete}));
		}
		/**
		 * You might need at some point to do somethign when the individual swf's load this would be the way to do it.
		 * 
		 * @param e :: SwfLoader 
		 */		
		private function onSwfLoadComplete(e:LoaderEvent):void
		{
			
			//var swfLoader:SWFLoader = e.target as SWFLoader;
			//var contentMC:ContentDisplay = swfLoader.content; // key step is the next one that gets the rawContent form the ContentDisplay
				//contentMC.rawContent.addEventListener(MetricsEvent.TRACK_ELEMENT, contentMetricsTracked, false, 0, true);
			
		}
		private function onPreloadComplete(e:LoaderEvent):void
		{
			dispatchEvent(new JukeBoxEvent(JukeBoxEvent.INIT));
			trace("ContentController.onPreloadComplete() ::  COMPLETE FIRED");
		}
		private function preloadProgressHandler(e:LoaderEvent):void 
		{		
			//trace("ContentController.preloadProgressHandler() progress: " + e.target.progress);
		}
		private function preloadErrorHandler(e:LoaderEvent):void 
		{
			trace("ContentController.preloadErrorHandler() :: ERROR :: " + e.type);
		}
		
		//---------------------------------------------------------
		// ACCESSORS
		public function get contentTime():Number
		{
			var cModel:ContentModel = _contentDic[_jukeBoxModel.id] as ContentModel;
			
			return cModel.time;
		}
	}
}